home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / DJLSR111.ZIP / libsrc / c / io / doscan.c < prev    next >
C/C++ Source or Header  |  1993-10-02  |  7KB  |  346 lines

  1. /* This is file DOSCAN.C */
  2. /* This file may have been modified by DJ Delorie (Jan 1991).  If so,
  3. ** these modifications are Coyright (C) 1993 DJ Delorie, 24 Kirsten Ave,
  4. ** Rochester NH, 03867-2954, USA.
  5. */
  6.  
  7. /* #define _doscan _____doscan */
  8. #include <stdio.h>
  9. #include <stdlib.h>  /* for atof */
  10. #include <ctype.h>
  11. #undef _doscan
  12.  
  13. #define    SPC    01
  14. #define    STP    02
  15.  
  16. #define    SHORT    0
  17. #define    REGULAR    1
  18. #define    LONG    2
  19. #define    INT    0
  20. #define    FLOAT    1
  21.  
  22. static int _innum(int **ptr, int type, int len, int size, FILE *iop, 
  23.                   int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), 
  24.                   int *eofptr);
  25. static int _instr(char *ptr, int type, int len, FILE *iop, 
  26.                   int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), 
  27.                   int *eofptr);
  28. static const char *_getccl(const unsigned char *s);
  29.  
  30. static char _sctab[256] = {
  31.     0,0,0,0,0,0,0,0,
  32.     0,SPC,SPC,SPC,SPC,SPC,0,0,
  33.     0,0,0,0,0,0,0,0,
  34.     0,0,0,0,0,0,0,0,
  35.     SPC,0,0,0,0,0,0,0,
  36.     0,0,0,0,0,0,0,0,
  37.     0,0,0,0,0,0,0,0,
  38.     0,0,0,0,0,0,0,0,
  39. };
  40.  
  41. static int nchars = 0;
  42.  
  43. int 
  44. _doscan(FILE *iop, const char *fmt, void **argp)
  45. {
  46.     return(_doscan_low(iop, fgetc, ungetc, fmt, argp));
  47. }
  48.  
  49. int
  50. _doscan_low(FILE *iop, int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *),
  51.             const char *fmt, void **argp)
  52. {
  53.     register int ch;
  54.     int nmatch, len, ch1;
  55.     int **ptr, fileended, size;
  56.  
  57.     nchars = 0;
  58.     nmatch = 0;
  59.     fileended = 0;
  60.     for (;;) switch (ch = *fmt++) {
  61.     case '\0': 
  62.         return (nmatch);
  63.     case '%': 
  64.         if ((ch = *fmt++) == '%')
  65.             goto def;
  66.         if (ch == 'n')
  67.         {
  68.           **(int **)argp++ = nchars;
  69.           break;
  70.         }
  71.         if (fileended)
  72.             return(nmatch? nmatch: -1);
  73.         ptr = 0;
  74.         if (ch != '*')
  75.             ptr = (int **)argp++;
  76.         else
  77.             ch = *fmt++;
  78.         len = 0;
  79.         size = REGULAR;
  80.         while (isdigit(ch)) {
  81.             len = len*10 + ch - '0';
  82.             ch = *fmt++;
  83.         }
  84.         if (len == 0)
  85.             len = 30000;
  86.         if (ch=='l') {
  87.             size = LONG;
  88.             ch = *fmt++;
  89.         } else if (ch=='h') {
  90.             size = SHORT;
  91.             ch = *fmt++;
  92.         } else if (ch=='[')
  93.             fmt = _getccl((const unsigned char *)fmt);
  94.         if (isupper(ch)) {
  95.             /* ch = tolower(ch);  
  96.                         gcc gives warning: ANSI C forbids braced
  97.                             groups within expressions */
  98.                         ch += 'a' - 'A';
  99.             size = LONG;
  100.         }
  101.         if (ch == '\0')
  102.             return(-1);
  103.         if (_innum(ptr, ch, len, size, iop, scan_getc, scan_ungetc, 
  104.                            &fileended) && ptr)
  105.             nmatch++;
  106.         break;
  107.  
  108.     case ' ':
  109.     case '\n':
  110.     case '\t': 
  111.     case '\r':
  112.     case '\f':
  113.     case '\v':
  114.         while (((nchars++, ch1 = scan_getc(iop))!=EOF) && (_sctab[ch1] & SPC))
  115.             ;
  116.         if (ch1 != EOF)
  117.         {
  118.             scan_ungetc(ch1, iop);
  119.         }
  120.         nchars--;
  121.         break;
  122.  
  123.     default: 
  124.     def:
  125.         ch1 = scan_getc(iop);
  126.         if (ch1 != EOF) nchars++;
  127.         if (ch1 != ch) {
  128.             if (ch1==EOF)
  129.                 return(-1);
  130.             scan_ungetc(ch1, iop);
  131.             nchars--;
  132.             return(nmatch);
  133.         }
  134.     }
  135. }
  136.  
  137. static int
  138. _innum(int **ptr, int type, int len, int size, FILE *iop, 
  139.        int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr)
  140. {
  141.     register char *np;
  142.     char numbuf[64];
  143.     register c, base;
  144.     int expseen, scale, negflg, c1, ndigit;
  145.     long lcval;
  146.     int cpos;
  147.  
  148.     if (type=='c' || type=='s' || type=='[')
  149.         return(_instr(ptr? *(char **)ptr: (char *)NULL, type, len, 
  150.                               iop, scan_getc, scan_ungetc, eofptr));
  151.     lcval = 0;
  152.     ndigit = 0;
  153.     scale = INT;
  154.     if (type=='e'||type=='f'||type=='g')
  155.         scale = FLOAT;
  156.     base = 10;
  157.     if (type=='o')
  158.         base = 8;
  159.     else if (type=='x')
  160.         base = 16;
  161.     np = numbuf;
  162.     expseen = 0;
  163.     negflg = 0;
  164.     while (((nchars++, c = scan_getc(iop)) != EOF) && (_sctab[c] & SPC))
  165.         ;
  166.     if (c == EOF) nchars--;
  167.     if (c=='-') {
  168.         negflg++;
  169.         *np++ = c;
  170.         c = scan_getc(iop);
  171.         nchars++;
  172.         len--;
  173.     } else if (c=='+') {
  174.         len--;
  175.         c = scan_getc(iop);
  176.         nchars++;
  177.     }
  178.     cpos = 0;
  179.     for ( ; --len>=0; *np++ = c, c = scan_getc(iop), nchars++) {
  180.         cpos++;
  181.         if (c == '0' && cpos == 1 && type == 'i')
  182.           base = 8;
  183.         if ((c == 'x' || c == 'X') && type == 'i' && cpos == 2)
  184.         {
  185.           base = 16;
  186.           continue;
  187.         }
  188.         if (isdigit(c)
  189.          || (base==16 && (('a'<=c && c<='f') || ('A'<=c && c<='F')))) {
  190.             ndigit++;
  191.             if (base==8)
  192.                 lcval <<=3;
  193.             else if (base==10)
  194.                 lcval = ((lcval<<2) + lcval)<<1;
  195.             else
  196.                 lcval <<= 4;
  197.             c1 = c;
  198.             if (isdigit(c))
  199.                 c -= '0';
  200.             else if ('a'<=c && c<='f')
  201.                 c -= 'a'-10;
  202.             else
  203.                 c -= 'A'-10;
  204.             lcval += c;
  205.             c = c1;
  206.             continue;
  207.         } else if (c=='.') {
  208.             if (base!=10 || scale==INT)
  209.                 break;
  210.             ndigit++;
  211.             continue;
  212.         } else if ((c=='e'||c=='E') && expseen==0) {
  213.             if (base!=10 || scale==INT || ndigit==0)
  214.                 break;
  215.             expseen++;
  216.             *np++ = c;
  217.             c = scan_getc(iop);
  218.             nchars++;
  219.             if (c!='+'&&c!='-'&&('0'>c||c>'9'))
  220.                 break;
  221.         } else
  222.             break;
  223.     }
  224.     if (negflg)
  225.         lcval = -lcval;
  226.     if (c != EOF) {
  227.         scan_ungetc(c, iop);
  228.         *eofptr = 0;
  229.     } else
  230.         *eofptr = 1;
  231.     nchars--;
  232.      if (ptr==NULL || np==numbuf || (negflg && np==numbuf+1) )/* gene dykes*/
  233.         return(0);
  234.     *np++ = 0;
  235.     switch((scale<<4) | size) {
  236.  
  237.     case (FLOAT<<4) | SHORT:
  238.     case (FLOAT<<4) | REGULAR:
  239.         **(float **)ptr = atof(numbuf);
  240.         break;
  241.  
  242.     case (FLOAT<<4) | LONG:
  243.         **(double **)ptr = atof(numbuf);
  244.         break;
  245.  
  246.     case (INT<<4) | SHORT:
  247.         **(short **)ptr = (short)lcval;
  248.         break;
  249.  
  250.     case (INT<<4) | REGULAR:
  251.         **(int **)ptr = (int)lcval;
  252.         break;
  253.  
  254.     case (INT<<4) | LONG:
  255.         **(long **)ptr = lcval;
  256.         break;
  257.     }
  258.     return(1);
  259. }
  260.  
  261. static int
  262. _instr(char *ptr, int type, int len, FILE *iop, 
  263.        int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr)
  264. {
  265.     register ch;
  266.     register char *optr;
  267.     int ignstp;
  268.  
  269.     *eofptr = 0;
  270.     optr = ptr;
  271.     if (type=='c' && len==30000)
  272.         len = 1;
  273.     ignstp = 0;
  274.     if (type=='s')
  275.         ignstp = SPC;
  276.     while ((nchars++, ch = scan_getc(iop)) != EOF && _sctab[ch] & ignstp)
  277.         ;
  278.     ignstp = SPC;
  279.     if (type=='c')
  280.         ignstp = 0;
  281.     else if (type=='[')
  282.         ignstp = STP;
  283.     while (ch!=EOF && (_sctab[ch]&ignstp)==0) {
  284.         if (ptr)
  285.             *ptr++ = ch;
  286.         if (--len <= 0)
  287.             break;
  288.         ch = scan_getc(iop);
  289.         nchars++;
  290.     }
  291.     if (ch != EOF) {
  292.         if (len > 0)
  293.         {
  294.             scan_ungetc(ch, iop);
  295.             nchars--;
  296.         }
  297.         *eofptr = 0;
  298.     } else
  299.         *eofptr = 1;
  300.     if (ptr && ptr!=optr) {
  301.         if (type!='c')
  302.             *ptr++ = '\0';
  303.         return(1);
  304.     }
  305.     return(0);
  306. }
  307.  
  308. static const char *
  309. _getccl(const unsigned char *s)
  310. {
  311.     register c, t;
  312.  
  313.     t = 0;
  314.     if (*s == '^') {
  315.         t++;
  316.         s++;
  317.     }
  318.     for (c = 0; c < (sizeof _sctab / sizeof _sctab[0]); c++)
  319.         if (t)
  320.             _sctab[c] &= ~STP;
  321.         else
  322.             _sctab[c] |= STP;
  323.     if ((c = *s) == ']' || c == '-') {    /* first char is special */
  324.         if (t)
  325.             _sctab[c] |= STP;
  326.         else
  327.             _sctab[c] &= ~STP;
  328.         s++;
  329.     }
  330.     while ((c = *s++) != ']') {
  331.         if (c==0)
  332.             return((const char *)--s);
  333.         else if (c == '-' && *s != ']' && s[-2] < *s) {
  334.             for (c = s[-2] + 1; c < *s; c++)
  335.                 if (t)
  336.                     _sctab[c] |= STP;
  337.                 else
  338.                     _sctab[c] &= ~STP;
  339.         } else if (t)
  340.             _sctab[c] |= STP;
  341.         else
  342.             _sctab[c] &= ~STP;
  343.     }
  344.     return((const char *)s);
  345. }
  346.